// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#ifdef _WIN32
    #include <stdint.h>
    #include <windows.h>
    #define FUNCTIONEXPORT
    #define FUNCTIONCALLINGCONVENTION WINAPI
#else
    #include "pal_types.h"
    #include "pal_compiler.h"
    #define FUNCTIONEXPORT PALEXPORT
    #define FUNCTIONCALLINGCONVENTION
#endif

/*
A structure that holds the input and output values for the zlib functions.
*/
typedef struct PAL_ZStream
{
    uint8_t* nextIn;  // next input byte
    uint8_t* nextOut; // next output byte should be put there

    char* msg; // last error message, NULL if no error

    // the underlying z_stream object is held in internalState, but it should not be used by external callers
    void* internalState;

    uint32_t availIn;  // number of bytes available at nextIn
    uint32_t availOut; // remaining free space at nextOut
} PAL_ZStream;

/*
Allowed flush values for the Deflate and Inflate functions.
*/
enum PAL_FlushCode
{
    PAL_Z_NOFLUSH = 0,
    PAL_Z_FINISH = 4,
};

/*
Error codes from the zlib functions.
*/
enum PAL_ErrorCode
{
    PAL_Z_OK = 0,
    PAL_Z_STREAMEND = 1,
    PAL_Z_STREAMERROR = -2,
    PAL_Z_DATAERROR = -3,
    PAL_Z_MEMERROR = -4,
    PAL_Z_BUFERROR = -5,
    PAL_Z_VERSIONERROR = -6
};

/*
Compression levels
*/
enum PAL_CompressionLevel
{
    PAL_Z_NOCOMPRESSION = 0,
    PAL_Z_BESTSPEED = 1,
    PAL_Z_DEFAULTCOMPRESSION = -1,
};

/*
Compression strategy
*/
enum PAL_CompressionStrategy
{
    PAL_Z_DEFAULTSTRATEGY = 0
};

/*
The deflate compression method (the only one supported in this version)
*/
enum PAL_CompressionMethod
{
    PAL_Z_DEFLATED = 8
};

/*
Initializes the PAL_ZStream so the Deflate function can be invoked on it.

Returns a PAL_ErrorCode indicating success or an error number on failure.
*/
FUNCTIONEXPORT int32_t FUNCTIONCALLINGCONVENTION CompressionNative_DeflateInit2_(
    PAL_ZStream* stream, int32_t level, int32_t method, int32_t windowBits, int32_t memLevel, int32_t strategy);

/*
Deflates (compresses) the bytes in the PAL_ZStream's nextIn buffer and puts the
compressed bytes in nextOut.

Returns a PAL_ErrorCode indicating success or an error number on failure.
*/
FUNCTIONEXPORT int32_t FUNCTIONCALLINGCONVENTION CompressionNative_Deflate(PAL_ZStream* stream, int32_t flush);

/*
All dynamically allocated data structures for this stream are freed.

Returns a PAL_ErrorCode indicating success or an error number on failure.
*/
FUNCTIONEXPORT int32_t FUNCTIONCALLINGCONVENTION CompressionNative_DeflateEnd(PAL_ZStream* stream);

/*
Initializes the PAL_ZStream so the Inflate function can be invoked on it.

Returns a PAL_ErrorCode indicating success or an error number on failure.
*/
FUNCTIONEXPORT int32_t FUNCTIONCALLINGCONVENTION CompressionNative_InflateInit2_(PAL_ZStream* stream, int32_t windowBits);

/*
Inflates (uncompresses) the bytes in the PAL_ZStream's nextIn buffer and puts the
uncompressed bytes in nextOut.

Returns a PAL_ErrorCode indicating success or an error number on failure.
*/
FUNCTIONEXPORT int32_t FUNCTIONCALLINGCONVENTION CompressionNative_Inflate(PAL_ZStream* stream, int32_t flush);

/*
All dynamically allocated data structures for this stream are freed.

Returns a PAL_ErrorCode indicating success or an error number on failure.
*/
FUNCTIONEXPORT int32_t FUNCTIONCALLINGCONVENTION CompressionNative_InflateEnd(PAL_ZStream* stream);

/*
This function is equivalent to InflateEnd followed by InflateInit, but does not free and reallocate 
the internal decompression state. The stream's window size will be modified and its memory may be
reallocated if necessary.

Returns a PAL_ErrorCode indicating success or an error number on failure.
*/
FUNCTIONEXPORT int32_t FUNCTIONCALLINGCONVENTION CompressionNative_InflateReset2_(PAL_ZStream* stream, int32_t windowBits);

/*
Update a running CRC-32 with the bytes buffer[0..len-1] and return the
updated CRC-32.

Returns the updated CRC-32.
*/
FUNCTIONEXPORT uint32_t FUNCTIONCALLINGCONVENTION CompressionNative_Crc32(uint32_t crc, uint8_t* buffer, int32_t len);
